home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part2 / 17661 < prev    next >
Encoding:
Text File  |  1996-08-05  |  4.2 KB  |  106 lines

  1. Path: kbad.eglin.af.mil!rpi!not-for-mail
  2. From: kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl)
  3. Newsgroups: comp.lang.c++.moderated,comp.lang.c++
  4. Subject: Re: I don't believe it! Weird thing about Virtual tables
  5. Followup-To: comp.lang.c++.moderated,comp.lang.c++
  6. Date: 16 Apr 1996 15:35:28 -0000
  7. Organization: FakultΣt fⁿr Mathematik und Informatik
  8. Sender: cppmods@netlab.cs.rpi.edu
  9. Approved: kanze@lts.sel.alcatel.de
  10. Message-ID: <4l0eo0$r44@netlab.cs.rpi.edu>
  11. References: <4ku0ee$hjj@netlab.cs.rpi.edu>
  12. Reply-To: dietmar.kuehl@uni-konstanz.de
  13. NNTP-Posting-Host: netlab.cs.rpi.edu
  14. X-Original-Date: 16 Apr 1996 09:16:55 GMT
  15.  
  16. Hi,
  17. Rodrigo de Salvo Braz (braz@ime.usp.br) wrote:
  18. : Debugging a project in Borland C++ 4.0, I noticed something
  19. : unexpected...
  20.  
  21. : The virtual table of one of my classes (say, Dog) is initialized by
  22. : code!
  23.  
  24. This is a reasonable thing to do: Remember that the virtual functions
  25. used may change in the process of constructing an object of a derived
  26. class. Consider e.g. this simple example:
  27.  
  28.   #include <iostream.h>
  29.  
  30.   class A
  31.   {
  32.   public:
  33.     virtual char const *f() { return "A::f()"; }
  34.     A() { cout << "A::A(): " << f() << endl; }
  35.     ~A() { cout << "A::~A(): " << f() << endl; }
  36.   };
  37.  
  38.   class B: public A
  39.   {
  40.   public:
  41.     virtual char const *f() { return "B::f()"; }
  42.     B() { cout << "B::B(): " << f() << endl; }
  43.     ~B() { cout << "B::~B(): " << f() << endl; }
  44.   };
  45.  
  46.   int main() { B b; return 0; }
  47.  
  48. The output of this simple program is
  49.  
  50. A::A(): A::f()
  51. B::B(): B::f()
  52. B::~B(): B::f()
  53. A::~A(): A::f()
  54.  
  55. This just demonstrates the rule that the call to a virtual function
  56. from a constructor or a destructor uses a static function lookup. To
  57. implement this easily, it is reasonable to initialize the virtual
  58. function table with the relevant table of the base class before the
  59. base class constructor is called. Then this virtual function table is
  60. replaced by the virtual function table for the derived class before the
  61. derived class constructor is called.  Likewise for the destructor.
  62.  
  63. :  It sounds ok at first, but since each module has its own initializing
  64. : code (for global variables and similar stuff), I have Dog's virtual
  65. : table initialized AFTER initializing code of modules located BEFORE
  66. : Dog's module in the Project definition. Since I have variables using
  67. : Dog in those earlier modules, I get a real crash!
  68.  
  69. The real problem is not that the virtual function table is not
  70. initialized but that your object is used before it is constructed:
  71. Since C++ provides no mechanism to define the order of construction
  72. (and destruction) of global objects, you should avoid using them, at
  73. least if some of your objects depend on others to be constructed when
  74. they are constructed themselves (or, in the reverse, that the objects
  75. are not yet destructed when they are destructed themselves). You can
  76. avoid this problem (for the construction of the objects) by wrapping
  77. the necessary global objects into functions like this:
  78.  
  79.   T &global_T() { static T object(/*...*/); return object; }
  80.  
  81. : So I have to worry about the modules definition order in the project
  82. : in order to have my program working properly, and that sounds really
  83. : odd!
  84.  
  85. Yes, this is odd because you rely on a very system dependent mechanism
  86. instead of removing the problem.
  87.  
  88. : Am doing any mistake on it? Is there any option preventing it? Why
  89. : doesn't the compiler create the virtual tables already initialized?
  90.  
  91. See above. Although the compiler can use a different mechanism to
  92. ensure that the virtual functions depend on the static type in the
  93. constructor and the destructor, there is no requirement to do so: Using
  94. a non-static member function on an object before construction begins,
  95. results in undefined behavior anyway (12.7 [class.cdtor] of the DWP).
  96. This is what you are attempting and what you get: undefined behavior.
  97. - --
  98. dietmar.kuehl@uni-konstanz.de
  99. http://www.informatik.uni-konstanz.de/~kuehl/
  100. I am a realistic optimist - that's why I appear to be slightly pessimistic
  101.  
  102.       [ Articles to moderate: mailto:c++-submit@netlab.cs.rpi.edu ]
  103.       [  Read the C++ FAQ: http://www.connobj.com/cpp/cppfaq.htm  ]
  104.       [  Moderation policy: http://www.connobj.com/cpp/guide.htm  ]
  105.       [      Comments? mailto:c++-request@netlab.cs.rpi.edu       ]
  106.